package com.ttn.student.service.impl;

import cn.hutool.core.util.NumberUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.ttn.common.core.entity.Result;
import com.ttn.common.core.entity.business.CourseUnitOralConversation;
import com.ttn.common.core.entity.studentrecord.*;
import com.ttn.common.core.entity.studentrecord.bo.SaveBatchOralConversationStudyRecordDetailsBO;
import com.ttn.common.core.entity.studentrecord.bo.TestStudyRecordBO;
import com.ttn.common.core.entity.studentrecord.query.QueryStudyLeaderboardQuery;
import com.ttn.common.core.entity.studentrecord.query.TestStudyRecordQuery;
import com.ttn.common.core.entity.studentrecord.vo.LikeRecordVO;
import com.ttn.common.core.entity.studentrecord.vo.SaveOralConversationStudyRecordDetailsVO;
import com.ttn.common.core.entity.studentrecord.vo.TestStudyRecordDetailsVO;
import com.ttn.common.core.entity.studentrecord.vo.TestStudyRecordVO;
import com.ttn.student.mapper.OralConversationStudyRecordDetailsMapper;
import com.ttn.student.service.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

@Service
public class OralConversationStudyRecordDetailsServiceImpl extends ServiceImpl<OralConversationStudyRecordDetailsMapper, OralConversationStudyRecordDetails> implements OralConversationStudyRecordDetailsService {
    @Resource
    private OralConversationStudyRecordDetailsMapper oralConversationStudyRecordDetailsMapper;
    @Resource
    private TestStudyRecordService testStudyRecordService;
    @Resource
    private LikeRecordService likeRecordService;
    @Resource
    private LearningProgressRecordService learningProgressRecordService;
    @Resource
    private StudentRecordService studentRecordService;

    @Override
    @Transactional
    public Result saveOralConversationStudyRecordDetails(SaveBatchOralConversationStudyRecordDetailsBO saveBatchOralConversationStudyRecordDetailsBO) {
        TestStudyRecordDetailsVO testStudyRecordDetailsVO = new TestStudyRecordDetailsVO();
        TestStudyRecordBO testStudyRecordBO = new TestStudyRecordBO();
        TestStudyRecord testStudyRecord = saveBatchOralConversationStudyRecordDetailsBO.getTestStudyRecord();
        testStudyRecordBO.setTestStudyRecord(testStudyRecord);
        testStudyRecordBO.setRestart(1);
        //获取答对题目数
        AtomicReference<Long> correctAnswerAtomic = new AtomicReference<>(0L);
        Result<TestStudyRecordVO> saveTestStudyRecordResult = testStudyRecordService.saveTestStudyRecord(testStudyRecordBO);
        if (saveTestStudyRecordResult.isSuccess() && Objects.nonNull(saveTestStudyRecordResult.getData())) {
            saveTestStudyRecordResult.getData().getTestStudyRecord().getId();
            saveBatchOralConversationStudyRecordDetailsBO.getOralConversationStudyRecordDetailsList().stream().forEach(oralConversationStudyRecordDetails -> {
                oralConversationStudyRecordDetails.setStudyRecordId(saveTestStudyRecordResult.getData().getTestStudyRecord().getId());
                oralConversationStudyRecordDetails.setCourseUnitId(saveTestStudyRecordResult.getData().getTestStudyRecord().getCourseUnitId());
                if (oralConversationStudyRecordDetails.getScore() >= 60) {
                    correctAnswerAtomic.getAndSet(correctAnswerAtomic.get() + 1);
                }
            });
            this.saveBatch(saveBatchOralConversationStudyRecordDetailsBO.getOralConversationStudyRecordDetailsList());
            saveTestStudyRecordResult.getData().getTestStudyRecord().setScore(Double.valueOf(saveBatchOralConversationStudyRecordDetailsBO.getOralConversationStudyRecordDetailsList().stream().mapToInt(OralConversationStudyRecordDetails::getScore).average().getAsDouble()).intValue());
            saveTestStudyRecordResult.getData().getTestStudyRecord().setFinishFlag(1);


//            LambdaQueryWrapper<TestStudyRecord> testStudyRecordLambdaQueryWrapper = new LambdaQueryWrapper<>();
            QueryWrapper<TestStudyRecord> testStudyRecordLambdaQueryWrapper = new QueryWrapper<>();
            testStudyRecordLambdaQueryWrapper.select(" DISTINCT student_id  ")
                    .lambda()
                    //获取所有答题用户数量
                    .eq(TestStudyRecord::getCourseUnitId, testStudyRecord.getCourseUnitId())
                    .eq(TestStudyRecord::getFinishFlag, 1)
                    .eq(TestStudyRecord::getUnitTaskType, "5")
                    .ne(TestStudyRecord::getStudentId, testStudyRecord.getStudentId());

            long countAll = testStudyRecordService.count(testStudyRecordLambdaQueryWrapper);
            testStudyRecordDetailsVO.setCompleted(Math.toIntExact(countAll));
            long beyondProportionNum = 0;
            if (countAll != 0) {
                //获取超过的用户
                testStudyRecordLambdaQueryWrapper.lambda().gt(TestStudyRecord::getScore, testStudyRecord.getScore());
                beyondProportionNum = testStudyRecordService.count(testStudyRecordLambdaQueryWrapper);
                //更新得分和排名
                testStudyRecord.setBeyondProportion(BigDecimal.valueOf(NumberUtil.mul(NumberUtil.sub(1, NumberUtil.div(beyondProportionNum, countAll, 2)), 100)));
            } else {
                testStudyRecord.setBeyondProportion(BigDecimal.valueOf(100));
            }
            //更新得分和排名
            saveTestStudyRecordResult.getData().getTestStudyRecord().setBeyondProportion(testStudyRecord.getBeyondProportion());

            saveTestStudyRecordResult.getData().getTestStudyRecord().setCorrectAmount(Math.toIntExact(correctAnswerAtomic.get()));
            saveTestStudyRecordResult.getData().getTestStudyRecord().setStudyNum(saveBatchOralConversationStudyRecordDetailsBO.getOralConversationStudyRecordDetailsList().size());
            //更新得分和排名
//            saveTestStudyRecordResult.getData().getTestStudyRecord().setBeyondProportion(BigDecimal.valueOf(NumberUtil.mul(NumberUtil.sub(1,
//                    NumberUtil.div(beyondProportionNum, countAll, 2)), 100)));
            testStudyRecordDetailsVO.setTestStudyRecord(testStudyRecord);

            testStudyRecordService.updateById(saveTestStudyRecordResult.getData().getTestStudyRecord());

            LambdaQueryWrapper<LearningProgressRecord> learningProgressRecordLambdaQueryWrapper =
                    new LambdaQueryWrapper<>();
            learningProgressRecordLambdaQueryWrapper.eq(LearningProgressRecord::getStudentId, testStudyRecord.getStudentId());
            learningProgressRecordLambdaQueryWrapper.eq(LearningProgressRecord::getCourseUnitId, testStudyRecord.getCourseUnitId());
            LearningProgressRecord learningProgressRecord =
                    learningProgressRecordService.getOne(learningProgressRecordLambdaQueryWrapper);
            learningProgressRecord.setCorrectAmount(testStudyRecordService.queryTotalCorrectAmountByUnitIdId(testStudyRecord.getCourseUnitId(), testStudyRecord.getStudentId()));
            if (testStudyRecord.getScore() >= 60) {
                learningProgressRecord.setFinishFlag(1);
                //调用升级方法
                learningProgressRecordService.queryJudgeGrade(testStudyRecord.getStudentId());
            }
            learningProgressRecordService.updateById(learningProgressRecord);
            List<SaveOralConversationStudyRecordDetailsVO> saveOralConversationStudyRecordDetailsVOS =
                    oralConversationStudyRecordDetailsMapper.getTop20(testStudyRecord);
            if (saveOralConversationStudyRecordDetailsVOS.size() > 0) {
                LambdaQueryWrapper<OralConversationStudyRecordDetails> oralConversationStudyRecordDetailsLambdaQueryWrapper2 =
                        new LambdaQueryWrapper<>();
                oralConversationStudyRecordDetailsLambdaQueryWrapper2.in(OralConversationStudyRecordDetails::getStudyRecordId
                        ,
                        saveOralConversationStudyRecordDetailsVOS.stream().map(SaveOralConversationStudyRecordDetailsVO::getId
                        ).collect(Collectors.toList()));
                //获取前20名音频文件
                List<OralConversationStudyRecordDetails> oralPracticeStudyRecordDetailsList =
                        this.list(oralConversationStudyRecordDetailsLambdaQueryWrapper2);
                if (oralPracticeStudyRecordDetailsList.size() > 0) {
                    List<String> spokenAudioFile = Lists.newArrayList();
                    Map<Integer, List<OralConversationStudyRecordDetails>> oralConversationStudyRecordDetailsMap =
                            oralPracticeStudyRecordDetailsList.stream().collect(Collectors.groupingBy(OralConversationStudyRecordDetails::getStudyRecordId));
                    saveOralConversationStudyRecordDetailsVOS.stream().forEach(saveOralConversationStudyRecordDetailsVO -> {
                        oralConversationStudyRecordDetailsMap.get(saveOralConversationStudyRecordDetailsVO.getId()).forEach(oralConversationStudyRecordDetails -> {
                            spokenAudioFile.add(oralConversationStudyRecordDetails.getAudioFile());
                            spokenAudioFile.add(oralConversationStudyRecordDetails.getUserAnswer());
                        });
                        saveOralConversationStudyRecordDetailsVO.setSpokenAudioFile(spokenAudioFile);

                    });
                }

                //获取点赞总数
                List<LikeRecordVO> likeRecordVOList =
                        likeRecordService.getLikeCount(saveOralConversationStudyRecordDetailsVOS.stream().map(SaveOralConversationStudyRecordDetailsVO::getId
                        ).collect(Collectors.toList()));
                if (likeRecordVOList.size() > 0) {
                    saveOralConversationStudyRecordDetailsVOS.stream().forEach(saveOralPracticeStudyRecordDetailsVO -> {
                        LikeRecordVO likeRecordVO =
                                likeRecordVOList.stream().filter(likeRecord -> likeRecord.getStudyRecordId().equals(saveOralPracticeStudyRecordDetailsVO.getId())).findFirst().orElse(null);
                        if (Objects.nonNull(likeRecordVO)) {
                            saveOralPracticeStudyRecordDetailsVO.setLikeNum(likeRecordVO.getLikeNum());
                        } else {
                            saveOralPracticeStudyRecordDetailsVO.setLikeNum(0);
                        }
                    });
                }

            }
            LambdaQueryWrapper<OralConversationStudyRecordDetails> oralConversationStudyRecordDetailsLambdaQueryWrapper = new LambdaQueryWrapper<>();
            oralConversationStudyRecordDetailsLambdaQueryWrapper.eq(OralConversationStudyRecordDetails::getStudyRecordId, testStudyRecord.getId());
            List<OralConversationStudyRecordDetails> userOralConversationStudyRecordDetailsList =
                    this.list(oralConversationStudyRecordDetailsLambdaQueryWrapper);
            if (userOralConversationStudyRecordDetailsList.size() > 0) {
                List<String> spokenAudioFile = Lists.newArrayList();
                userOralConversationStudyRecordDetailsList.forEach(oralConversationStudyRecordDetails -> {
                    spokenAudioFile.add(oralConversationStudyRecordDetails.getAudioFile());
                    spokenAudioFile.add(oralConversationStudyRecordDetails.getUserAnswer());
                });
                testStudyRecordDetailsVO.setSpokenAudioFile(spokenAudioFile);
            }

            testStudyRecordDetailsVO.setOralConversationStudyRecordDetails(saveOralConversationStudyRecordDetailsVOS);
            testStudyRecordDetailsVO.setRanking(Math.toIntExact(beyondProportionNum + 1));
            StudentRecord studentRecord = studentRecordService.getById(testStudyRecord.getStudentId());
            if (Objects.nonNull(studentRecord)) {
                testStudyRecordDetailsVO.setAvatarUrl(studentRecord.getAvatarUrl());
            }

        }

        return Result.success(testStudyRecordDetailsVO);
    }

    @Override
    public List<CourseUnitOralConversation> getUnfinishedCourseUnitOralConversationList(TestStudyRecord testStudyRecord) {
        return oralConversationStudyRecordDetailsMapper.getUnfinishedCourseUnitOralConversationList(testStudyRecord);
    }

    @Override
    public Result queryOralConversationLeaderboard(QueryStudyLeaderboardQuery queryStudyLeaderboardQuery) {
        TestStudyRecordDetailsVO testStudyRecordDetailsVO = new TestStudyRecordDetailsVO();
        LambdaQueryWrapper<TestStudyRecord> testStudyRecordLambdaQueryWrapper = new LambdaQueryWrapper<>();
        testStudyRecordLambdaQueryWrapper.eq(TestStudyRecord::getFinishFlag, 1);
        testStudyRecordLambdaQueryWrapper.eq(TestStudyRecord::getCourseUnitId, queryStudyLeaderboardQuery.getCourseUnitId());
        testStudyRecordLambdaQueryWrapper.eq(TestStudyRecord::getStudentId, queryStudyLeaderboardQuery.getStudentId());
        testStudyRecordLambdaQueryWrapper.eq(TestStudyRecord::getUnitTaskType, "5");
        testStudyRecordLambdaQueryWrapper.last(" limit 1");
        testStudyRecordLambdaQueryWrapper.orderByDesc(TestStudyRecord::getScore);
        TestStudyRecord testStudyRecord = testStudyRecordService.getOne(testStudyRecordLambdaQueryWrapper);
        if (Objects.nonNull(testStudyRecord)) {
            testStudyRecordDetailsVO.setTestStudyRecord(testStudyRecord);
            StudentRecord studentRecord = studentRecordService.getById(testStudyRecord.getStudentId());
            if (Objects.nonNull(studentRecord)) {
                testStudyRecordDetailsVO.setAvatarUrl(studentRecord.getAvatarUrl());
            }
            List<SaveOralConversationStudyRecordDetailsVO> saveOralConversationStudyRecordDetailsVOS =
                    oralConversationStudyRecordDetailsMapper.getTop20(testStudyRecord);
            if (saveOralConversationStudyRecordDetailsVOS.size() > 0) {
                LambdaQueryWrapper<OralConversationStudyRecordDetails> oralConversationStudyRecordDetailsLambdaQueryWrapper2 =
                        new LambdaQueryWrapper<>();
                oralConversationStudyRecordDetailsLambdaQueryWrapper2.in(OralConversationStudyRecordDetails::getStudyRecordId
                        ,
                        saveOralConversationStudyRecordDetailsVOS.stream().map(SaveOralConversationStudyRecordDetailsVO::getId
                        ).collect(Collectors.toList()));
                //获取前20名音频文件
                List<OralConversationStudyRecordDetails> oralPracticeStudyRecordDetailsList =
                        this.list(oralConversationStudyRecordDetailsLambdaQueryWrapper2);
                if (oralPracticeStudyRecordDetailsList.size() > 0) {
                    List<String> spokenAudioFile = Lists.newArrayList();
                    Map<Integer, List<OralConversationStudyRecordDetails>> oralConversationStudyRecordDetailsMap =
                            oralPracticeStudyRecordDetailsList.stream().collect(Collectors.groupingBy(OralConversationStudyRecordDetails::getStudyRecordId));
                    saveOralConversationStudyRecordDetailsVOS.stream().forEach(saveOralConversationStudyRecordDetailsVO -> {
                        oralConversationStudyRecordDetailsMap.get(saveOralConversationStudyRecordDetailsVO.getId()).forEach(oralConversationStudyRecordDetails -> {
                            spokenAudioFile.add(oralConversationStudyRecordDetails.getAudioFile());
                            spokenAudioFile.add(oralConversationStudyRecordDetails.getUserAnswer());
                        });
                        saveOralConversationStudyRecordDetailsVO.setSpokenAudioFile(spokenAudioFile);

                    });
                }

                //获取点赞总数
                List<LikeRecordVO> likeRecordVOList =
                        likeRecordService.getLikeCount(saveOralConversationStudyRecordDetailsVOS.stream().map(SaveOralConversationStudyRecordDetailsVO::getId
                        ).collect(Collectors.toList()));
                if (likeRecordVOList.size() > 0) {
                    saveOralConversationStudyRecordDetailsVOS.stream().forEach(saveOralPracticeStudyRecordDetailsVO -> {
                        LikeRecordVO likeRecordVO =
                                likeRecordVOList.stream().filter(likeRecord -> likeRecord.getStudyRecordId().equals(saveOralPracticeStudyRecordDetailsVO.getId())).findFirst().orElse(null);
                        if (Objects.nonNull(likeRecordVO)) {
                            saveOralPracticeStudyRecordDetailsVO.setLikeNum(likeRecordVO.getLikeNum());
                        } else {
                            saveOralPracticeStudyRecordDetailsVO.setLikeNum(0);
                        }
                    });
                }

            }
            LambdaQueryWrapper<OralConversationStudyRecordDetails> oralConversationStudyRecordDetailsLambdaQueryWrapper = new LambdaQueryWrapper<>();
            oralConversationStudyRecordDetailsLambdaQueryWrapper.eq(OralConversationStudyRecordDetails::getStudyRecordId, testStudyRecord.getId());
            List<OralConversationStudyRecordDetails> userOralConversationStudyRecordDetailsList =
                    this.list(oralConversationStudyRecordDetailsLambdaQueryWrapper);
            if (userOralConversationStudyRecordDetailsList.size() > 0) {
                List<String> spokenAudioFile = Lists.newArrayList();
                userOralConversationStudyRecordDetailsList.forEach(oralConversationStudyRecordDetails -> {
                    spokenAudioFile.add(oralConversationStudyRecordDetails.getAudioFile());
                    spokenAudioFile.add(oralConversationStudyRecordDetails.getUserAnswer());
                });
                testStudyRecordDetailsVO.setSpokenAudioFile(spokenAudioFile);
            }
            testStudyRecordDetailsVO.setOralConversationStudyRecordDetails(saveOralConversationStudyRecordDetailsVOS);
            QueryWrapper<TestStudyRecord> studyRecordLambdaQueryWrapperCount = new QueryWrapper<>();
            studyRecordLambdaQueryWrapperCount.select(" DISTINCT student_id  ")
                    .lambda()
                    //获取所有答题用户数量
                    .eq(TestStudyRecord::getCourseUnitId, testStudyRecord.getCourseUnitId())
                    .eq(TestStudyRecord::getFinishFlag, 1)
                    .eq(TestStudyRecord::getUnitTaskType, "5")
                    .ne(TestStudyRecord::getStudentId, testStudyRecord.getStudentId());
            testStudyRecordDetailsVO.setCompleted(Math.toIntExact(testStudyRecordService.count(studyRecordLambdaQueryWrapperCount) + 1));


            LambdaQueryWrapper<TestStudyRecord> studyRecordLambdaQueryWrapper = new LambdaQueryWrapper<>();
            //获取所有答题用户数量
            studyRecordLambdaQueryWrapper.eq(TestStudyRecord::getCourseUnitId, testStudyRecord.getCourseUnitId());
            studyRecordLambdaQueryWrapper.eq(TestStudyRecord::getFinishFlag, 1);
            studyRecordLambdaQueryWrapper.eq(TestStudyRecord::getUnitTaskType, "5");
            studyRecordLambdaQueryWrapper.gt(TestStudyRecord::getScore, testStudyRecord.getScore());
            testStudyRecordDetailsVO.setRanking(Math.toIntExact(testStudyRecordService.count(studyRecordLambdaQueryWrapper) + 1));
            LambdaQueryWrapper<LikeRecord> likeRecordLambdaQueryWrapper = new LambdaQueryWrapper<>();
            likeRecordLambdaQueryWrapper.eq(LikeRecord::getStudyRecordId, testStudyRecord.getId());
            testStudyRecordDetailsVO.setLikeNum(Math.toIntExact(likeRecordService.count(likeRecordLambdaQueryWrapper)));

        }

        return Result.success(testStudyRecordDetailsVO);
    }

    @Override
    public Result queryOralConversationStudyRecordDetails(TestStudyRecordQuery testStudyRecordQuery) {
        TestStudyRecordDetailsVO testStudyRecordDetailsVO = new TestStudyRecordDetailsVO();
        LambdaQueryWrapper<TestStudyRecord> testStudyRecordLambdaQueryWrapper = new LambdaQueryWrapper<>();
        testStudyRecordLambdaQueryWrapper.eq(TestStudyRecord::getStudentId, testStudyRecordQuery.getStudentId());
        testStudyRecordLambdaQueryWrapper.eq(TestStudyRecord::getCourseUnitId, testStudyRecordQuery.getCourseUnitId());
        testStudyRecordLambdaQueryWrapper.eq(TestStudyRecord::getUnitTaskType, "5");
        testStudyRecordLambdaQueryWrapper.eq(TestStudyRecord::getFinishFlag, 1);
        testStudyRecordLambdaQueryWrapper.orderByDesc(TestStudyRecord::getScore);
        testStudyRecordLambdaQueryWrapper.last(" limit 1");
        TestStudyRecord testStudyRecord = testStudyRecordService.getOne(testStudyRecordLambdaQueryWrapper);
        if (Objects.nonNull(testStudyRecord)) {
            testStudyRecordDetailsVO.setTestStudyRecord(testStudyRecord);
            LambdaQueryWrapper<OralConversationStudyRecordDetails> oralConversationStudyRecordDetailsLambdaQueryWrapper = new LambdaQueryWrapper<>();
            oralConversationStudyRecordDetailsLambdaQueryWrapper.eq(OralConversationStudyRecordDetails::getStudyRecordId, testStudyRecord.getId());
            List<OralConversationStudyRecordDetails> userOralConversationStudyRecordDetailsList =
                    this.list(oralConversationStudyRecordDetailsLambdaQueryWrapper);
            if (userOralConversationStudyRecordDetailsList.size() > 0) {
                List<String> spokenAudioFile = Lists.newArrayList();
                userOralConversationStudyRecordDetailsList.forEach(oralConversationStudyRecordDetails -> {
                    spokenAudioFile.add(oralConversationStudyRecordDetails.getAudioFile());
                    spokenAudioFile.add(oralConversationStudyRecordDetails.getUserAnswer());
                });
                testStudyRecordDetailsVO.setSpokenAudioFile(spokenAudioFile);
            }
        }
        return Result.success(testStudyRecordDetailsVO);
    }


}
